package com.phenix.network.base

import com.phenix.network.environment.IEnvironment
import com.phenix.network.environment.INetworkRequired
import com.phenix.network.interceptor.RequestInterceptor
import com.phenix.network.interceptor.ResponseInterceptor
import com.phenix.network.response.MoshiResultTypeAdapterFactory
import com.phenix.network.response.NetworkResponseAdapterFactory
import com.squareup.moshi.Moshi
import com.squareup.moshi.kotlin.reflect.KotlinJsonAdapterFactory
import okhttp3.Interceptor
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.converter.moshi.MoshiConverterFactory

abstract class BaseNetworkApi(env: IEnvironment) {
    private var mRetrofit: Retrofit


    companion object {
        private lateinit var networkRequired: INetworkRequired

        private var globalErrorHandler: NetworkResponseAdapterFactory.FailureHandler? = null

        private var isDevelopment = true

        fun init(isDevelopment: Boolean = true, networkRequired: INetworkRequired) {
            this.isDevelopment = isDevelopment
            this.networkRequired = networkRequired
        }

        fun setGlobalErrorHandler(globalErrorHandler: NetworkResponseAdapterFactory.FailureHandler?) {
            this.globalErrorHandler = globalErrorHandler
        }
    }

    open fun <T> getService(service: Class<T>): T = mRetrofit.create(service)

    init {
        val envelope: Envelope? by lazy {
            getEnvelopeHandler()
        }

        val okHttpClient: OkHttpClient by lazy {
            OkHttpClient.Builder().apply {
                addInterceptor(RequestInterceptor(networkRequired))
                addInterceptor(ResponseInterceptor())
                getInterceptor()?.let { interceptor ->
                    addInterceptor(interceptor)
                }
                networkRequired.takeIf { it.isDebugMode() }.apply {
                    addInterceptor(HttpLoggingInterceptor().apply {
                        setLevel(HttpLoggingInterceptor.Level.BODY)
                    })
                }
            }.build()
        }

        val moshi = Moshi.Builder()
            .add(MoshiResultTypeAdapterFactory(envelope))
            .addLast(KotlinJsonAdapterFactory())
            .build()

        val errorEnvelope: Envelope by lazy {
            getErrorEnvelope()
        }

        mRetrofit = Retrofit.Builder()
            .baseUrl(env.getBaseUrl(isDevelopment))
            .addConverterFactory(MoshiConverterFactory.create(moshi))
            .client(okHttpClient)
            .addCallAdapterFactory(NetworkResponseAdapterFactory(globalErrorHandler, errorEnvelope))
            .build()
    }


    protected abstract fun getInterceptor(): Interceptor?
    protected abstract fun getErrorEnvelope(): Envelope

    /**
     * 去信封 {code: 0, message: "", data: "data"} => "data"
     */
    protected open fun getEnvelopeHandler(): Envelope? {
        return null
    }

}
